#include "class.h"

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

///foo
class(foo)
{
    void (*hello)();
};

static void foo_hello()
{
    printf("Hello\n");
}

class_impl(foo){
    hello : foo_hello
};

constructor(foo)
{
    printf("foo constructor\n");
}

destructor(foo)
{
    printf("foo destructor\n");
}

constructor(foo, int i)
{
    printf("foo constructor %d\n", i);
}

constructor(foo, int i, int a)
{
    printf("foo constructor %d\n", i);
}

///bar
class(bar, foo)
{
    void (*world)();
};

constructor(bar)
{
    printf("bar constructor\n");
}

destructor(bar)
{
    printf("bar destructor\n");
}

static void bar_world()
{
    printf("world\n");
}

class_impl(bar, foo){
    world : bar_world
};

class(vector)
{
    void **arr;
    int size;
    int capacity;
    void (*print)(vector * this);
    void (*append)(vector * this, void *obj);
};

static void vector_print(vector *this)
{
    printf("vector_print size:%d\n", this->size);
}

static void vector_append(vector *this, void *obj)
{
    this->arr[this->size++] = obj;
    printf("vector_append size:%d\n", this->size);
}

class_impl(vector){
    arr : NULL,
    size : 0,
    capacity : 0,
    print : vector_print,
    append : vector_append,
};

constructor(vector)
{
    printf("constructor(vector), %p %p\n",this, this->arr);

    this->arr = malloc(sizeof(void *) * 100);
    this->capacity = 100;
    this->size = 0;
}

destructor(vector)
{
    printf("destructor(vector),%p %p\n",this, this->arr);
    for (int i = 0; i < this->size; i++)
    {
        if (this->arr[i] != NULL)
        {
            delete (this->arr[i]);
        }
    }
    free(this->arr);
}

int main()
{
    do_init_class();

    {
        foo *p_foo = new (foo);
        p_foo->hello();
        delete (p_foo);
    }
    {
        bar *p_bar = new (bar);
        foo *p_foo = dynamic_cast(foo)(p_bar);
        p_foo->hello();
        p_bar->world();
        delete (p_foo);
    }

    {
        vector *p_vec = new (vector);
        $(p_vec, append)(new (foo));
        $(p_vec, append)(new (foo));
        $(p_vec, print)();
        delete (p_vec);
    }
    return 0;
}